#ifndef __M_HELPER_H__
#define __M_HELPER_H__
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <random>
#include <sstream>
#include <iomanip>
#include <atomic>
#include <sqlite3.h>
#include <cstring>
#include <cerrno>
#include <sys/stat.h>
#include "logger.hpp"

namespace bitmq 
{

/**
 * @brief SQLite数据库操作封装类
 * @note 提供数据库连接管理、SQL执行等基础功能
 */
class SqliteHelper 
{
public:
    typedef int(*SqliteCallback)(void*,int,char**,char**); ///< SQLite回调函数类型定义
    
    /**
     * @brief 构造函数
     * @param dbfile 数据库文件路径
     */
    explicit SqliteHelper(const std::string &dbfile) 
        : _dbfile(dbfile), _handler(nullptr){}
    
    /**
     * @brief 打开数据库连接
     * @param safe_level 安全级别标志（默认为SQLITE_OPEN_FULLMUTEX）
     * @return 成功返回true，失败返回false并记录错误日志
     * @warning 失败后会自动记录错误信息，但不会关闭数据库句柄
     */
    bool open(int safe_level = SQLITE_OPEN_FULLMUTEX) {
        int ret = sqlite3_open_v2(
            _dbfile.c_str(), 
            &_handler, 
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_level, 
            nullptr
        );
        if (ret != SQLITE_OK) {
            ELOG("创建/打开sqlite数据库失败: %s", sqlite3_errmsg(_handler));
            return false;
        }
        return true;
    }

    /**
     * @brief 执行SQL语句
     * @param sql 要执行的SQL语句
     * @param cb 回调函数指针
     * @param arg 回调函数参数
     * @return 执行成功返回true，失败返回false并记录错误日志
     */
    bool exec(const std::string &sql, SqliteCallback cb, void *arg) {
        int ret = sqlite3_exec(_handler, sql.c_str(), cb, arg, nullptr);
        if (ret != SQLITE_OK) {
            ELOG("%s \n语句执行失败: %s", sql.c_str(), sqlite3_errmsg(_handler));
            return false;
        }
        return true;
    }

    /// @brief 关闭数据库连接
    void close() {
        if (_handler) sqlite3_close_v2(_handler);
    }

private:
    std::string _dbfile;    ///< 数据库文件路径
    sqlite3 *_handler;      ///< SQLite数据库句柄
};

/**
 * @brief 字符串处理工具类
 * @note 提供字符串分割等常用功能
 */
class StrHelper {
public:
    /**
     * @brief 字符串分割函数
     * @param str 输入字符串
     * @param sep 分隔符
     * @param result 存储分割结果的vector
     * @return 分割后的元素数量
     * @note 自动过滤空字符串，支持多字符分隔符
     * @example split("a,b,c", ",", result) -> ["a","b","c"]
     */
    static size_t split(const std::string &str, 
                      const std::string &sep,
                      std::vector<std::string> &result) {
        size_t pos, idx = 0;
        while(idx < str.size()) {
            pos = str.find(sep, idx);
            if (pos == std::string::npos) {
                if (idx != str.size()) {
                    result.push_back(str.substr(idx));
                }
                break;
            }
            if (pos == idx) {  // 处理连续分隔符情况
                idx = pos + sep.size();
                continue;
            }
            result.push_back(str.substr(idx, pos - idx));
            idx = pos + sep.size();
        }
        return result.size();
    }
};

/**
 * @brief UUID生成工具类
 * @note 生成符合格式的伪随机UUID字符串
 */
class UUIDHelper {
public:
    /**
     * @brief 生成UUID字符串
     * @return 格式示例：3cd2b7a4-6b27-471f-8000-000000000001
     * @note 前8字节为随机数，后8字节为自增序列，不完全符合UUID规范
     */
    static std::string uuid() {
        // 随机数部分（前8字节）
        std::random_device rd;
        std::mt19937_64 generator(rd());
        std::uniform_int_distribution<int> distribution(0, 255);
        std::stringstream ss;
        for (int i = 0; i < 8; i++) {
            ss << std::setw(2) << std::setfill('0') 
               << std::hex << distribution(generator);
            if (i == 3 || i == 5 || i == 7) {
                ss << "-";
            }
        }

        // 自增序列部分（后8字节）
        static std::atomic<size_t> seq(1);  // 原子计数器保证线程安全
        size_t num = seq.fetch_add(1);
        for (int i = 7; i >= 0; i--) {
            ss << std::setw(2) << std::setfill('0') 
               << std::hex << ((num >> (i * 8)) & 0xff);
            if (i == 6) ss << "-";
        }
        return ss.str();
    }
};

/**
 * @brief 文件操作工具类
 * @note 提供文件读写、目录操作等常用功能
 */
class FileHelper 
{
public:
    /**
     * @brief 构造函数
     * @param filename 目标文件名
     */
    explicit FileHelper(const std::string &filename)
        :_filename(filename){}

    /// @brief 检查文件是否存在
    bool exists() 
    {
        struct stat st;
        return (stat(_filename.c_str(), &st) == 0);
    }

    /// @brief 获取文件大小（字节）
    size_t size() 
    {
        struct stat st;
        return (stat(_filename.c_str(), &st) == 0) ? st.st_size : 0;
    }

    /**
     * @brief 从指定位置读取文件内容
     * @param body 存储读取数据的缓冲区
     * @param offset 读取起始偏移量
     * @param len 要读取的长度
     * @return 读取成功返回true，失败记录日志并返回false
     */
    bool read(char *body, size_t offset, size_t len) 
    {
        std::ifstream ifs(_filename, std::ios::binary | std::ios::in); 
        if (!ifs.is_open()) 
        {
            ELOG("%s 文件打开失败！", _filename.c_str());
            return false;
        }
        ifs.seekg(offset, std::ios::beg);
        ifs.read(body, len);
        if (!ifs.good()) 
        {
            ELOG("%s 文件读取数据失败！", _filename.c_str());
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }

    /// @brief 读取整个文件内容到字符串
    bool read(std::string &body) 
    {
        size_t fsize = this->size();
        body.resize(fsize);
        return read(&body[0], 0, fsize);
    }

    /**
     * @brief 向文件指定位置写入数据
     * @warning 文件不存在时会自动创建
     * @param body 待写入数据指针
     * @param offset 写入起始偏移量
     * @param len 写入数据长度
     */
    bool write(const char *body, size_t offset, size_t len) 
    {
        std::fstream fs(_filename, std::ios::binary | std::ios::in | std::ios::out); 
        if (!fs.is_open()) 
        {
            ELOG("%s 文件打开失败！", _filename.c_str());
            return false;
        }
        fs.seekp(offset, std::ios::beg);
        fs.write(body, len);
        if (!fs.good()) 
        {
            ELOG("%s 文件写入失败！", _filename.c_str());
            fs.close();
            return false;
        }
        fs.close();
        return true;
    }

    /// @brief 写入整个字符串到文件
    bool write(const std::string &body) 
    {
        return write(body.c_str(), 0, body.size());
    }

    /// @brief 文件重命名
    bool rename(const std::string &nname) 
    {
        return (::rename(_filename.c_str(), nname.c_str()) == 0);
    }

    /**
     * @brief 获取父目录路径
     * @example "/path/to/file.txt" -> "/path/to"
     */
    static std::string parentDirectory(const std::string &filename) 
    {
        size_t pos = filename.find_last_of("/");
        return (pos == std::string::npos) ? "./" : filename.substr(0, pos);
    }

    /// @brief 创建空文件
    static bool createFile(const std::string &filename) 
    {
        std::fstream ofs(filename, std::ios::binary | std::ios::out); 
        if (!ofs.is_open()) 
        {
            ELOG("%s 文件创建失败！", filename.c_str());
            return false;
        }
        ofs.close();
        return true;
    }

    /// @brief 删除文件
    static bool removeFile(const std::string &filename) 
    {
        return (::remove(filename.c_str()) == 0);
    }

    /**
     * @brief 递归创建目录
     * @note 自动创建多级不存在的父目录
     * @example "a/b/c" 会依次创建a, a/b, a/b/c
     */
    static bool createDirectory(const std::string &path) 
    {
        size_t pos, idx = 0;
        while(idx < path.size()) 
        {
            pos = path.find("/", idx);
            std::string subpath = (pos == std::string::npos) 
                ? path 
                : path.substr(0, pos);
            
            int ret = mkdir(subpath.c_str(), 0775);
            if (ret != 0 && errno != EEXIST) 
            {
                ELOG("创建目录 %s 失败: %s", subpath.c_str(), strerror(errno));
                return false;
            }
            if (pos == std::string::npos) break;
            idx = pos + 1;
        }
        return true;
    }

    /**
     * @brief 递归删除目录
     * @warning 使用系统命令实现，存在安全风险
     * @recommend 建议使用C++17 filesystem替代
     */
    static bool removeDirectory(const std::string &path) 
    {
        std::string cmd = "rm -rf " + path;
        return (system(cmd.c_str()) != -1);
    }

private:
    std::string _filename;  // 操作的目标文件名
};

} // namespace bitmq
#endif